﻿using System;
using System.Collections;
using System.Collections.Generic;
using QxFramework.Utilities;

namespace QxFramework.Core
{
    /// <summary>
    /// 窗口管理，管理整个软件窗口的切换。
    /// </summary>
    public class WindowManager : Singleton<WindowManager>, ISystemModule
    {
        ///<summary>
        /// 获取当前窗口
        /// </summary>
        public WindowBase Current
        {
            get { return _current; }
        }

        ///<summary>
        /// 获取上一个窗口
        /// </summary>
        public WindowBase Previous
        {
            get { return _previous; }
        }

        ///<summary>
        /// 当前窗口
        /// </summary>
        private WindowBase _current;

        ///<summary>
        /// 上一个窗口
        /// </summary>
        private WindowBase _previous;

        private readonly Dictionary<Type, WindowBase> _windowDictionary = new Dictionary<Type, WindowBase>();

        /// <summary>
        /// 初始化函数，实例化所有窗口并完成初始化。
        /// </summary>
        public void Initialize()
        {
            //获取所有窗口的名字
            string[] windows = Utilities.TypeUtilities.GetTypeNames(typeof(WindowBase));

            for (int i = 0; i < windows.Length; i++)
            {
                Type t = Type.GetType(windows[i]);
                WindowBase win = Activator.CreateInstance(t) as WindowBase;
                _windowDictionary[t] = win;

                win.OnInit();
            }
        }

        /// <summary>
        /// 将窗口切换至另一个窗口。
        /// </summary>
        /// <typeparam name="T">窗口类型。</typeparam>
        public void ChangeTo<T>(object args = null) where T : WindowBase
        {
            //切换至下一个窗口
            ChangeTo(_windowDictionary[typeof(T)], args);
            System.GC.Collect();
            UnityEngine.Resources.UnloadUnusedAssets();
        }

        /// <summary>
        /// 将窗口切换至另一个窗口。
        /// </summary>
        /// <param name="win">流程对象。</param>
        public void ChangeTo(WindowBase win, object args = null)
        {
            //执行上一个窗口的离开函数
            if (_current != null)
            {
                _current.OnLeave();
            }
            //保存上一个流程
            _previous = _current;

            if (_windowDictionary.ContainsValue(win))
            {
                //进入下一个窗口
                _current = win;
                //执行进入的函数
                win.OnEnter(args);
            }
            else
            {
                //该流程不是默认创建的流程，抛出异常
                throw new ArgumentException();
            }
        }

        /// <summary>
        /// 更新窗口。
        /// </summary>
        /// <param name="elapseSeconds">流逝时间，以秒为单位。</param>
        public void Update(float elapseSeconds)
        {
            if (_current != null)
            {
                _current.OnUpdate(elapseSeconds);
            }
        }

        /// <summary>
        /// 物理更新窗口。
        /// </summary>
        /// <param name="elapseSeconds">流逝时间，以秒为单位。</param>
        public void FixedUpdate(float elapseSeconds)
        {
            if (_current != null)
            {
                _current.OnFixedUpdate(elapseSeconds);
            }
        }

        /// <summary>
        /// 退出时执行。
        /// </summary>
        public void Dispose()
        {
            foreach (var pair in _windowDictionary)
            {
                //执行所有的退出函数
                pair.Value.OnDestroy();
            }
        }
    }
}